#include "TaskQueue.h"
/**
 * @param queSize
 */
TaskQueue::TaskQueue(size_t queSize) 
    :_queSize(queSize)
    ,_que()
    ,_mutex()
    ,_notFull()
    ,_notEmpty()
     ,_flag(true)    
{}

/**
 * @param value：const int &
 * @return void
 */
void TaskQueue::push(ElemType &value) {
    //1.加锁
    /* _mutex.lock(); */

    //使用c++之父提出的RAII的思想
    //核心:利用栈对象的生命周期管理资源
    unique_lock<mutex> autoLock(_mutex);

    //2.判断
    /* if(full()){ */
    while(full()){  //防止虚假唤醒
        //2.1如果队列是满的，生产者需要睡眠
        _notFull.wait(autoLock);
    }
    //2.1如果队列不为满，加入队列,并且唤醒生产者队列
    _que.push_back(value);
    _notEmpty.notify_one();
    //3.解锁
    /* _mutex.unlock(); */
}

/**
 * @return int
 */
ElemType TaskQueue::pop() {
    //1.加锁
    /* _mutex.lock(); */

    //利用RAII技术实现自动解锁
    unique_lock<mutex> autoLock(_mutex);

    //2.判断
    /* if(empty()){ */
    while(empty() && _flag){  //防止虚假唤醒
        //2.1队列为空,消费者需要睡眠
        _notEmpty.wait(autoLock);
    }
    if(_flag == true){

        //2.2执行pop,并且唤醒生产者队列
        ElemType result = _que.front();
        _que.pop_front();
        //唤醒生产者队列
        _notFull.notify_one();
        //3.解锁
        /* _mutex.unlock(); */
        return result;
    }else{
        return nullptr;
    }

}

/**
 * @return bool
 */
bool TaskQueue::full() {
    return _queSize == _que.size();
}

/**
 * @return bool
 */
bool TaskQueue::empty() {
    return 0 == _que.size();
}

void TaskQueue::wakeup(){
    _flag = false;
    _notEmpty.notify_all();  //在线程池结束之前，唤醒因为任务队列为空引起的阻塞。
    //因为此种阻塞会引起线程池无法退出的问题，而_notfull的的阻塞是没有引起问题的
}

TaskQueue::~TaskQueue() {

}
